// 自定义线
import shapeStyle from '../utils/defaultStyle';

export default function(G6) {
    G6.registerEdge(
        'flow-cubic-round',
        {
            drawShape(cfg, group) {
                this.group = group;
                const shapeStyle = this.getShapeStyle(cfg);
                const shape = group.addShape('path', {
                    className: 'edge-shape',
                    attrs: shapeStyle,
                });
                return shape;
            },
            drawLabel(cfg, group) {
                const labelCfg = cfg.labelCfg || {};
                const labelStyle = this.getLabelStyle(cfg, labelCfg, group);
                const label = group.addShape('text', {
                    attrs: labelStyle,
                });
                const labelBBox = label.getBBox();
                group.addShape('rect', {
                    className: 'edge-labelRect',
                    attrs: {
                        x: labelBBox.x - shapeStyle.edgeLabelRectPadding / 2,
                        y: labelBBox.y - shapeStyle.edgeLabelRectPadding / 2,
                        width: labelBBox.width + shapeStyle.edgeLabelRectPadding,
                        height: labelBBox.height + shapeStyle.edgeLabelRectPadding,
                        fill: '#fff',
                        stroke: '#fff',
                    },
                });
                group.toBack();
                label.toFront();
                return label;
            },
            afterUpdate(cfg, item) {
                const label = item.getContainer().findByClassName('edge-label');
                const labelRect = item.getContainer().findByClassName('edge-labelRect');
                if (label) {
                    const labelBBox = label.getBBox();
                    labelRect.attr({
                        x: labelBBox.x - shapeStyle.edgeLabelRectPadding / 2,
                        y: labelBBox.y - shapeStyle.edgeLabelRectPadding / 2,
                        width: labelBBox.width + shapeStyle.edgeLabelRectPadding,
                        height: labelBBox.height + shapeStyle.edgeLabelRectPadding,
                    });
                }
            },
            getShapeStyle(cfg) {
                cfg = this.getPathPoints(cfg);
                const startPoint = cfg.startPoint;
                const endPoint = cfg.endPoint;
                const controlPoints = this.getControlPoints(cfg);
                let points = [startPoint];
                if (controlPoints) {
                    points = points.concat(controlPoints);
                }
                points.push(endPoint);
                const path = this.getPath(points);
                let style = shapeStyle.edgeStyle;
                if (cfg.reverse) style = { ...style, lineDash: [1, 3] };
                else style = { ...style, lineDash: null };
                return {
                    path,
                    ...style,
                    endArrow: {
                        path: 'M 0,0 L 6,-2 Q 5 0,6 2 Z',
                        fill: shapeStyle.edgeStyle.stroke,
                    },
                };
            },
            getPath(points) {
                const path = [];
                path.push(['M', points[0].x, points[0].y]);
                path.push(['C', points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y]);
                path.push(['V', points[4].y]);
                return path;
            },
            getControlPoints(cfg) {
                if (!cfg.sourceNode) {
                    return cfg.controlPoints;
                }

                const { startPoint, endPoint } = cfg;
                const frontEndPoint = {
                    x: endPoint.x,
                    y: endPoint.y - 10,
                };
                let innerPoint1 = {
                    x: startPoint.x,
                };
                let innerPoint2 = {
                    x: frontEndPoint.x,
                };

                //startPoint.y,endPoint.y
                const yDiff = frontEndPoint.y - startPoint.y;
                if (yDiff >= 100) {
                    innerPoint1.y = (frontEndPoint.y - startPoint.y) * this.curvePosition[0] + startPoint.y;
                    innerPoint2.y = (frontEndPoint.y - startPoint.y) * this.curvePosition[1] + startPoint.y;
                } else if (yDiff > 50 && yDiff < 100) {
                    innerPoint1.y = frontEndPoint.y;
                    innerPoint2.y = startPoint.y;
                } else {
                    innerPoint1.y = (50 - yDiff) / 3 + 50 + startPoint.y;
                    innerPoint2.y = frontEndPoint.y - ((50 - yDiff) / 3 + 50);
                }
                const controlPoints = [innerPoint1, innerPoint2, frontEndPoint];
                return controlPoints;
            },
            setState(name, value, item) {
                const group = item.getContainer();
                const path = group.getChildByIndex(0);
                if (name === 'selected') {
                    if (!item.hasState('running')) {
                        if (value) {
                            path.attr('lineWidth', shapeStyle.edgeSelectedStyle.lineWidth);
                            path.attr('stroke', shapeStyle.edgeStyle.stroke);
                        } else {
                            path.attr('lineWidth', shapeStyle.edgeStyle.lineWidth);
                        }
                    }
                } else if (name === 'hover') {
                    if (value) path.attr('stroke', shapeStyle.edgeActivedStyle.stroke);
                    else path.attr('stroke', shapeStyle.edgeStyle.stroke);
                } else if (name === 'running') {
                    const shape = item.get('keyShape');
                    if (value) {
                        const dashArray = [
                            [0, 1],
                            [0, 2],
                            [1, 2],
                            [0, 1, 1, 2],
                            [0, 2, 1, 2],
                            [1, 2, 1, 2],
                            [2, 2, 1, 2],
                            [3, 2, 1, 2],
                            [4, 2, 1, 2],
                        ];
                        const lineDash = [4, 2, 1, 2];
                        const interval = dashArray.length;

                        const length = shape.getTotalLength();
                        let totalArray = [];
                        for (let i = 0; i < length; i += interval) {
                            totalArray = totalArray.concat(lineDash);
                        }

                        path.attr('stroke', shapeStyle.edgeRunningStyle.stroke);
                        let index = 0;
                        let total = 0;
                        // 边 path 图形的动画
                        shape.animate(
                            {
                                // 动画重复
                                repeat: true,
                                // 每一帧的操作，入参 ratio：这一帧的比例值（Number）。返回值：这一帧需要变化的参数集（Object）。
                                onFrame() {
                                    const cfg = {
                                        lineDash: dashArray[index].concat(totalArray),
                                    };
                                    // 每次移动 1
                                    total += 0.5;
                                    index = Math.floor(total % interval);
                                    if (index === interval) {
                                        total = 0;
                                    }
                                    // 返回需要修改的参数集，这里只修改了 lineDash
                                    return cfg;
                                },
                            },
                            3000
                        ); // 一次动画的时长为 3000
                    } else {
                        path.attr('stroke', shapeStyle.edgeStyle.stroke);
                        // running 状态为 false 时
                        // 结束动画
                        shape.stopAnimate();
                        // 清空 lineDash
                        shape.attr('lineDash', null);
                    }
                }
            },
        },
        'cubic'
    );
}
